/**
 * 通用工具函数库
 * 提供常用的工具方法，提高代码复用性
 */

import { message } from 'ant-design-vue'
import { DATE_FORMAT, TAG_COLORS, CATEGORY_COLORS, REGEX_PATTERNS } from '@/constants'

/**
 * 日期格式化工具
 */
export const dateUtils = {
  /**
   * 格式化日期
   * @param {Date|string|number} date - 日期对象、字符串或时间戳
   * @param {string} format - 格式化模板，默认 'YYYY-MM-DD'
   * @returns {string} 格式化后的日期字符串
   */
  format(date, format = DATE_FORMAT.DEFAULT) {
    if (!date) return ''

    const d = new Date(date)
    if (isNaN(d.getTime())) return ''

    const year = d.getFullYear()
    const month = String(d.getMonth() + 1).padStart(2, '0')
    const day = String(d.getDate()).padStart(2, '0')
    const hours = String(d.getHours()).padStart(2, '0')
    const minutes = String(d.getMinutes()).padStart(2, '0')
    const seconds = String(d.getSeconds()).padStart(2, '0')

    return format
      .replace('YYYY', year)
      .replace('MM', month)
      .replace('DD', day)
      .replace('HH', hours)
      .replace('mm', minutes)
      .replace('ss', seconds)
  },

  /**
   * 获取相对时间描述
   * @param {Date|string|number} date - 日期
   * @returns {string} 相对时间描述
   */
  getRelativeTime(date) {
    if (!date) return ''

    const now = new Date()
    const target = new Date(date)
    const diff = now.getTime() - target.getTime()

    const minute = 60 * 1000
    const hour = 60 * minute
    const day = 24 * hour
    const month = 30 * day
    const year = 365 * day

    if (diff < minute) {
      return '刚刚'
    } else if (diff < hour) {
      return `${Math.floor(diff / minute)}分钟前`
    } else if (diff < day) {
      return `${Math.floor(diff / hour)}小时前`
    } else if (diff < month) {
      return `${Math.floor(diff / day)}天前`
    } else if (diff < year) {
      return `${Math.floor(diff / month)}个月前`
    } else {
      return `${Math.floor(diff / year)}年前`
    }
  },

  /**
   * 判断是否为今天
   * @param {Date|string|number} date - 日期
   * @returns {boolean}
   */
  isToday(date) {
    if (!date) return false

    const today = new Date()
    const target = new Date(date)

    return today.toDateString() === target.toDateString()
  }
}

/**
 * 字符串处理工具
 */
export const stringUtils = {
  /**
   * 截断字符串
   * @param {string} str - 原字符串
   * @param {number} length - 最大长度
   * @param {string} suffix - 后缀，默认 '...'
   * @returns {string} 截断后的字符串
   */
  truncate(str, length, suffix = '...') {
    if (!str || str.length <= length) return str
    return str.substring(0, length) + suffix
  },

  /**
   * 首字母大写
   * @param {string} str - 原字符串
   * @returns {string} 首字母大写的字符串
   */
  capitalize(str) {
    if (!str) return ''
    return str.charAt(0).toUpperCase() + str.slice(1)
  },

  /**
   * 驼峰转连字符
   * @param {string} str - 驼峰字符串
   * @returns {string} 连字符字符串
   */
  kebabCase(str) {
    if (!str) return ''
    return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
  },

  /**
   * 连字符转驼峰
   * @param {string} str - 连字符字符串
   * @returns {string} 驼峰字符串
   */
  camelCase(str) {
    if (!str) return ''
    return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
  },

  /**
   * 移除HTML标签
   * @param {string} str - 包含HTML的字符串
   * @returns {string} 纯文本字符串
   */
  stripHtml(str) {
    if (!str) return ''
    return str.replace(/<[^>]*>/g, '')
  },

  /**
   * 提取摘要
   * @param {string} content - 文章内容
   * @param {number} maxLength - 最大长度
   * @returns {string} 摘要
   */
  extractSummary(content, maxLength = 200) {
    if (!content) return ''

    // 移除HTML标签和Markdown语法
    const cleanText = content
      .replace(/<[^>]*>/g, '') // 移除HTML标签
      .replace(/[#*`_~]/g, '') // 移除Markdown语法
      .replace(/\n+/g, ' ') // 将换行符替换为空格
      .trim()

    return this.truncate(cleanText, maxLength)
  }
}

/**
 * 数组处理工具
 */
export const arrayUtils = {
  /**
   * 数组去重
   * @param {Array} arr - 原数组
   * @param {string} key - 对象数组的去重键名
   * @returns {Array} 去重后的数组
   */
  unique(arr, key) {
    if (!Array.isArray(arr)) return []

    if (key) {
      const seen = new Set()
      return arr.filter(item => {
        const value = item[key]
        if (seen.has(value)) {
          return false
        }
        seen.add(value)
        return true
      })
    }

    return [...new Set(arr)]
  },

  /**
   * 数组分组
   * @param {Array} arr - 原数组
   * @param {string|Function} key - 分组键名或分组函数
   * @returns {Object} 分组后的对象
   */
  groupBy(arr, key) {
    if (!Array.isArray(arr)) return {}

    return arr.reduce((groups, item) => {
      const groupKey = typeof key === 'function' ? key(item) : item[key]
      if (!groups[groupKey]) {
        groups[groupKey] = []
      }
      groups[groupKey].push(item)
      return groups
    }, {})
  },

  /**
   * 数组排序
   * @param {Array} arr - 原数组
   * @param {string} key - 排序键名
   * @param {string} order - 排序方向 'asc' | 'desc'
   * @returns {Array} 排序后的数组
   */
  sortBy(arr, key, order = 'asc') {
    if (!Array.isArray(arr)) return []

    return [...arr].sort((a, b) => {
      const aVal = a[key]
      const bVal = b[key]

      if (aVal < bVal) return order === 'asc' ? -1 : 1
      if (aVal > bVal) return order === 'asc' ? 1 : -1
      return 0
    })
  },

  /**
   * 分页处理
   * @param {Array} arr - 原数组
   * @param {number} page - 页码（从1开始）
   * @param {number} pageSize - 每页数量
   * @returns {Object} 分页结果
   */
  paginate(arr, page = 1, pageSize = 10) {
    if (!Array.isArray(arr)) return { data: [], total: 0, page: 1, pageSize }

    const total = arr.length
    const startIndex = (page - 1) * pageSize
    const endIndex = startIndex + pageSize
    const data = arr.slice(startIndex, endIndex)

    return {
      data,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    }
  }
}

/**
 * 验证工具
 */
export const validationUtils = {
  /**
   * 验证邮箱
   * @param {string} email - 邮箱地址
   * @returns {boolean}
   */
  isEmail(email) {
    return REGEX_PATTERNS.EMAIL.test(email)
  },

  /**
   * 验证手机号
   * @param {string} phone - 手机号
   * @returns {boolean}
   */
  isPhone(phone) {
    return REGEX_PATTERNS.PHONE.test(phone)
  },

  /**
   * 验证URL
   * @param {string} url - URL地址
   * @returns {boolean}
   */
  isUrl(url) {
    return REGEX_PATTERNS.URL.test(url)
  },

  /**
   * 验证密码强度
   * @param {string} password - 密码
   * @returns {boolean}
   */
  isStrongPassword(password) {
    return REGEX_PATTERNS.PASSWORD.test(password)
  },

  /**
   * 验证是否为空
   * @param {any} value - 值
   * @returns {boolean}
   */
  isEmpty(value) {
    if (value === null || value === undefined) return true
    if (typeof value === 'string') return value.trim() === ''
    if (Array.isArray(value)) return value.length === 0
    if (typeof value === 'object') return Object.keys(value).length === 0
    return false
  }
}

/**
 * 本地存储工具
 */
export const storageUtils = {
  /**
   * 设置本地存储
   * @param {string} key - 键名
   * @param {any} value - 值
   * @param {number} expire - 过期时间（毫秒）
   */
  set(key, value, expire) {
    const data = {
      value,
      expire: expire ? Date.now() + expire : null
    }
    localStorage.setItem(key, JSON.stringify(data))
  },

  /**
   * 获取本地存储
   * @param {string} key - 键名
   * @returns {any} 值
   */
  get(key) {
    try {
      const item = localStorage.getItem(key)
      if (!item) return null

      const data = JSON.parse(item)

      // 检查是否过期
      if (data.expire && Date.now() > data.expire) {
        localStorage.removeItem(key)
        return null
      }

      return data.value
    } catch (error) {
      console.error('获取本地存储失败:', error)
      return null
    }
  },

  /**
   * 删除本地存储
   * @param {string} key - 键名
   */
  remove(key) {
    localStorage.removeItem(key)
  },

  /**
   * 清空本地存储
   */
  clear() {
    localStorage.clear()
  }
}

/**
 * URL工具
 */
export const urlUtils = {
  /**
   * 获取URL参数
   * @param {string} name - 参数名
   * @param {string} url - URL地址，默认为当前页面URL
   * @returns {string|null} 参数值
   */
  getParam(name, url = window.location.href) {
    const urlObj = new URL(url)
    return urlObj.searchParams.get(name)
  },

  /**
   * 设置URL参数
   * @param {Object} params - 参数对象
   * @param {string} url - URL地址，默认为当前页面URL
   * @returns {string} 新的URL
   */
  setParams(params, url = window.location.href) {
    const urlObj = new URL(url)

    Object.keys(params).forEach(key => {
      if (params[key] !== null && params[key] !== undefined) {
        urlObj.searchParams.set(key, params[key])
      } else {
        urlObj.searchParams.delete(key)
      }
    })

    return urlObj.toString()
  },

  /**
   * 删除URL参数
   * @param {string|Array} names - 参数名或参数名数组
   * @param {string} url - URL地址，默认为当前页面URL
   * @returns {string} 新的URL
   */
  removeParams(names, url = window.location.href) {
    const urlObj = new URL(url)
    const nameArray = Array.isArray(names) ? names : [names]

    nameArray.forEach(name => {
      urlObj.searchParams.delete(name)
    })

    return urlObj.toString()
  }
}

/**
 * 颜色工具
 */
export const colorUtils = {
  /**
   * 获取随机标签颜色
   * @returns {string} 颜色名称
   */
  getRandomTagColor() {
    return TAG_COLORS[Math.floor(Math.random() * TAG_COLORS.length)]
  },

  /**
   * 获取随机分类颜色
   * @returns {string} 颜色名称
   */
  getRandomCategoryColor() {
    return CATEGORY_COLORS[Math.floor(Math.random() * CATEGORY_COLORS.length)]
  },

  /**
   * 根据字符串生成固定颜色
   * @param {string} str - 字符串
   * @param {Array} colors - 颜色数组
   * @returns {string} 颜色名称
   */
  getColorByString(str, colors = TAG_COLORS) {
    if (!str) return colors[0]

    let hash = 0
    for (let i = 0; i < str.length; i++) {
      hash = str.charCodeAt(i) + ((hash << 5) - hash)
    }

    return colors[Math.abs(hash) % colors.length]
  }
}

/**
 * 防抖函数
 * @param {Function} func - 要防抖的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, delay) {
  let timeoutId

  return function (...args) {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => func.apply(this, args), delay)
  }
}

/**
 * 节流函数
 * @param {Function} func - 要节流的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @returns {Function} 节流后的函数
 */
export function throttle(func, delay) {
  let lastCall = 0

  return function (...args) {
    const now = Date.now()
    if (now - lastCall >= delay) {
      lastCall = now
      func.apply(this, args)
    }
  }
}

/**
 * 复制到剪贴板
 * @param {string} text - 要复制的文本
 * @returns {Promise<boolean>} 是否复制成功
 */
export async function copyToClipboard(text) {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(text)
      message.success('复制成功')
      return true
    } else {
      // 降级方案
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'fixed'
      textArea.style.left = '-999999px'
      textArea.style.top = '-999999px'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()

      const success = document.execCommand('copy')
      document.body.removeChild(textArea)

      if (success) {
        message.success('复制成功')
        return true
      } else {
        throw new Error('复制失败')
      }
    }
  } catch (error) {
    console.error('复制失败:', error)
    message.error('复制失败')
    return false
  }
}

/**
 * 文件大小格式化
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数
 * @returns {string} 格式化后的文件大小
 */
export function formatFileSize(bytes, decimals = 2) {
  if (!+bytes) return '0 Bytes'

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}

/**
 * 生成随机ID
 * @param {number} length - ID长度
 * @returns {string} 随机ID
 */
export function generateId(length = 8) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''

  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }

  return result
}

/**
 * 深拷贝
 * @param {any} obj - 要拷贝的对象
 * @returns {any} 深拷贝后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj)
  if (obj instanceof Array) return obj.map(item => deepClone(item))

  if (typeof obj === 'object') {
    const clonedObj = {}
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        clonedObj[key] = deepClone(obj[key])
      }
    }
    return clonedObj
  }
}

// 导出所有工具函数
export default {
  dateUtils,
  stringUtils,
  arrayUtils,
  validationUtils,
  storageUtils,
  urlUtils,
  colorUtils,
  debounce,
  throttle,
  copyToClipboard,
  formatFileSize,
  generateId,
  deepClone
}